/*!
 * \file IDataReader.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 数据读取接口定义
 * \details 定义了数据读取模块的核心接口，包括数据读取回调、历史数据加载器和主要数据读取功能
 */
#pragma once
#include <stdint.h>

#include "../Includes/WTSMarcos.h"
#include "../Includes/WTSTypes.h"

NS_WTP_BEGIN
class WTSKlineData;
class WTSKlineSlice;
class WTSTickSlice;
class WTSOrdQueSlice;
class WTSOrdDtlSlice;
class WTSTransSlice;
struct WTSBarStruct;
class WTSVariant;
class IBaseDataMgr;
class IHotMgr;

/**
 * @class IDataReaderSink
 * @brief 数据读取模块回调接口
 * @details 定义了数据读取模块与其他模块交互的回调接口。
 *          主要功能包括：
 *          - K线合成事件回调
 *          - 全部K线更新完成通知
 *          - 基础数据管理器访问
 *          - 热门合约管理器访问
 *          - 当前时间信息获取
 *          
 *          该接口由数据使用方实现，用于接收数据读取模块的通知。
 */
class IDataReaderSink
{
public:
	/**
	 * @brief K线合成事件回调
	 * @details 当数据读取模块合成新的K线时触发此回调，通知相关模块进行处理。
	 *          适用于实时数据处理场景。
	 *	
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param period K线周期类型
	 * @param newBar 合成的K线结构指针
	 */
	virtual void on_bar(const char* stdCode, WTSKlinePeriod period, WTSBarStruct* newBar) = 0;

	/**
	 * @brief 所有品种K线全部更新的事件回调
	 * @details 当一个时间节点的所有品种K线都更新完成时触发。
	 *          用于批量处理完成的通知。
	 * 
	 * @param updateTime K线更新时间，精确到分钟，格式如202004101500
	 */
	virtual void on_all_bar_updated(uint32_t updateTime) = 0;

	/**
	 * @brief 获取基础数据管理接口指针
	 * @details 提供对基础数据管理器的访问，用于获取合约信息、交易日历等基础数据。
	 * 
	 * @return IBaseDataMgr* 基础数据管理器指针
	 */
	virtual IBaseDataMgr*	get_basedata_mgr() = 0;

	/**
	 * @brief 获取主力合约管理接口指针
	 * @details 提供对热门合约管理器的访问，用于获取主力合约、连续合约等信息。
	 * 
	 * @return IHotMgr* 热门合约管理器指针
	 */
	virtual IHotMgr*		get_hot_mgr() = 0;

	/**
	 * @brief 获取当前日期
	 * @details 获取系统当前的交易日期。
	 * 
	 * @return uint32_t 当前日期，格式如20100410
	 */
	virtual uint32_t	get_date() = 0;

	/**
	 * @brief 获取当前1分钟线的时间
	 * @details 返回的分钟时间是从当前分钟减1分钟的时间。
	 *          例如当前为9:00:32秒，实际记录为0900，对应的1分钟时间为0901。
	 *          用于确定当前正在形成的K线时间戳。
	 * 
	 * @return uint32_t 当前1分钟线时间，格式如0901
	 */
	virtual uint32_t	get_min_time() = 0;

	/**
	 * @brief 获取当前秒数
	 * @details 获取当前时间的秒数部分，精确到毫秒。
	 * 
	 * @return uint32_t 当前秒数，精确到毫秒，格式如37500表示37.5秒
	 */
	virtual uint32_t	get_secs() = 0;

	/**
	 * @brief 数据读取模块日志记录
	 * @details 用于数据读取模块输出日志信息。
	 * 
	 * @param ll 日志级别
	 * @param message 日志消息内容
	 */
	virtual void		reader_log(WTSLogLevel ll, const char* message) = 0;
};


/**
 * @typedef FuncReadBars
 * @brief 历史数据读取的回调函数类型
 * @details 用于历史K线数据读取完成后的回调通知。
 * 
 * @param obj 回调调用的对象，原样传回给调用者
 * @param bars K线数据数组
 * @param count K线数据数量
 */
typedef void(*FuncReadBars)(void* obj, WTSBarStruct* bars, uint32_t count);

/**
 * @typedef FuncReadFactors
 * @brief 复权因子读取回调函数类型
 * @details 用于复权因子数据读取完成后的回调通知。
 * 
 * @param obj 回调调用的对象，原样传回给调用者
 * @param stdCode 合约代码
 * @param dates 日期数组
 * @param factors 复权因子数组
 * @param count 数据数量
 */
typedef void(*FuncReadFactors)(void* obj, const char* stdCode, uint32_t* dates, double* factors, uint32_t count);

/**
 * @class IHisDataLoader
 * @brief 历史数据加载器接口
 * @details 提供历史数据加载功能的接口，支持原始数据和复权数据的加载。
 *          主要功能包括：
 *          - 最终历史K线数据加载（含复权处理）
 *          - 原始历史K线数据加载（未复权）
 *          - 复权因子数据加载
 *          
 *          loadFinalHisBars和loadRawHisBars的区别：
 *          - loadFinalHisBars：系统认为是最终的数据，用于进行加工处理，如复权数据、连续合约等
 *          - loadRawHisBars：加载未加工的原始数据
 */
class IHisDataLoader
{
public:
	/**
	 * @brief 加载最终的历史K线数据
	 * @details 加载经过处理的最终历史K线数据，包括复权处理、连续合约处理等。
	 *          这是系统推荐使用的历史数据接口。
	 * 
	 * @param obj 回调调用的对象，原样传回给调用者
	 * @param stdCode 合约代码
	 * @param period K线周期
	 * @param cb 回调函数
	 * @return bool 加载是否成功
	 */
	virtual bool loadFinalHisBars(void* obj, const char* stdCode, WTSKlinePeriod period, FuncReadBars cb) = 0;

	/**
	 * @brief 加载原始的历史K线数据
	 * @details 加载未经过任何处理的原始历史K线数据。
	 *          适用于需要原始数据进行特殊处理的场景。
	 * 
	 * @param obj 回调调用的对象，原样传回给调用者
	 * @param stdCode 合约代码
	 * @param period K线周期
	 * @param cb 回调函数
	 * @return bool 加载是否成功
	 */
	virtual bool loadRawHisBars(void* obj, const char* stdCode, WTSKlinePeriod period, FuncReadBars cb) = 0;

	/**
	 * @brief 加载全部复权因子
	 * @details 加载系统中所有股票的复权因子数据。
	 * 
	 * @param obj 回调调用的对象
	 * @param cb 回调函数
	 * @return bool 加载是否成功
	 */
	virtual bool loadAllAdjFactors(void* obj, FuncReadFactors cb) = 0;

	/**
	 * @brief 加载指定合约的复权因子
	 * @details 加载特定股票代码的复权因子数据。
	 * 
	 * @param obj 回调调用的对象
	 * @param stdCode 股票代码
	 * @param cb 回调函数
	 * @return bool 加载是否成功
	 */
	virtual bool loadAdjFactors(void* obj, const char* stdCode, FuncReadFactors cb) = 0;
};

/**
 * @class IDataReader
 * @brief 数据读取接口
 * @details 数据读取模块提供的核心数据（tick和K线）读取接口。
 *          主要功能包括：
 *          - 模块初始化和配置
 *          - 分钟级别事件处理
 *          - 各类市场数据切片读取（tick、K线、委托、成交等）
 *          - 复权因子获取
 *          
 *          该接口是数据读取模块的核心，由具体的数据存储实现类继承。
 */
class IDataReader
{
public:
	IDataReader() :_sink(NULL) {}
	virtual ~IDataReader(){}

public:
	/**
	 * @brief 初始化数据读取模块
	 * @details 使用配置参数初始化数据读取模块，设置回调接口和历史数据加载器。
	 * 
	 * @param cfg 模块配置参数
	 * @param sink 模块回调接口
	 * @param loader 历史数据加载器，可选参数
	 */
	virtual void init(WTSVariant* cfg, IDataReaderSink* sink, IHisDataLoader* loader = NULL) { _sink = sink; _loader = loader; }

	/**
	 * @brief 分钟线合成事件处理接口
	 * @details 每分钟结束时调用，用于触发K线合成和相关数据处理。
	 *	
	 * @param uDate 合成的分钟所在交易日，格式如20200410，这里不是自然日
	 * @param uTime 合成的分钟线的分钟时间，格式如1115
	 * @param endTDate 如果合成的分钟是交易日的最后一个分钟，endTDate为当前交易日，格式如20200410，否则为0
	 */
	virtual void onMinuteEnd(uint32_t uDate, uint32_t uTime, uint32_t endTDate = 0) = 0;

	/**
	 * @brief 获取tick数据切片
	 * @details 切片是倒序的数据，只把缓存中的数据指针传递出来，可以节约内存片。
	 *          用于获取指定数量的最新tick数据。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param count 要获取的tick数量
	 * @param etime 结束时间，精确到毫秒，格式如yyyyMMddhhmmssmmm，如果要获取最后一条，etime为0，默认为0
	 * @return WTSTickSlice* tick数据切片，使用完需要释放
	 */
	virtual WTSTickSlice*	readTickSlice(const char* stdCode, uint32_t count, uint64_t etime = 0) = 0;

	/**
	 * @brief 获取逐笔委托数据切片
	 * @details 切片是倒序的数据，只把缓存中的数据指针传递出来，可以节约内存片。
	 *          用于获取Level2逐笔委托数据。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param count 要获取的数据数量
	 * @param etime 结束时间，精确到毫秒，格式如yyyyMMddhhmmssmmm，如果要获取最后一条，etime为0，默认为0
	 * @return WTSOrdDtlSlice* 逐笔委托数据切片，不支持时返回NULL
	 */
	virtual WTSOrdDtlSlice*	readOrdDtlSlice(const char* stdCode, uint32_t count, uint64_t etime = 0) { return NULL; }
	
	/**
	 * @brief 获取委托队列数据切片
	 * @details 切片是倒序的数据，只把缓存中的数据指针传递出来，可以节约内存片。
	 *          用于获取Level2委托队列数据。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param count 要获取的数据数量
	 * @param etime 结束时间，精确到毫秒，格式如yyyyMMddhhmmssmmm，如果要获取最后一条，etime为0，默认为0
	 * @return WTSOrdQueSlice* 委托队列数据切片，不支持时返回NULL
	 */
	virtual WTSOrdQueSlice*	readOrdQueSlice(const char* stdCode, uint32_t count, uint64_t etime = 0) { return NULL; }

	/**
	 * @brief 获取逐笔成交数据切片
	 * @details 切片是倒序的数据，只把缓存中的数据指针传递出来，可以节约内存片。
	 *          用于获取Level2逐笔成交数据。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param count 要获取的数据数量
	 * @param etime 结束时间，精确到毫秒，格式如yyyyMMddhhmmssmmm，如果要获取最后一条，etime为0，默认为0
	 * @return WTSTransSlice* 逐笔成交数据切片，不支持时返回NULL
	 */
	virtual WTSTransSlice*	readTransSlice(const char* stdCode, uint32_t count, uint64_t etime = 0) { return NULL; }

	/**
	 * @brief 获取K线切片，这是主要的数据接口
	 * @details 切片是倒序的数据，只把缓存中的数据指针传递出来，可以节约内存片。
	 *          这是策略获取历史K线数据的主要接口。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000,SHFE.au.2005
	 * @param period K线周期
	 * @param count 要获取的K线数量
	 * @param etime 结束时间，格式yyyyMMddhhmm
	 * @return WTSKlineSlice* K线数据切片，使用完需要释放
	 */
	virtual WTSKlineSlice*	readKlineSlice(const char* stdCode, WTSKlinePeriod period, uint32_t count, uint64_t etime = 0) = 0;

	/**
	 * @brief 获取股票指定日期的复权因子
	 * @details 用于股票数据的复权计算，获取指定日期的复权因子。
	 * 
	 * @param stdCode 标准品种代码，格式如SSE.600000
	 * @param date 指定日期，格式yyyyMMdd，默认为0，为0则按当前日期处理
	 * @return double 复权因子，默认返回1.0
	 */
	virtual double		getAdjFactorByDate(const char* stdCode, uint32_t date = 0) { return 1.0; }

protected:
	IDataReaderSink*	_sink;		///< 数据读取回调接口
	IHisDataLoader*		_loader;	///< 历史数据加载器
};

/**
 * @typedef FuncCreateDataReader
 * @brief 创建数据读取器函数指针类型
 * @details 用于动态库中创建数据读取器实例的函数指针。
 */
typedef IDataReader* (*FuncCreateDataReader)();

/**
 * @typedef FuncDeleteDataReader
 * @brief 删除数据读取器函数指针类型
 * @details 用于动态库中删除数据读取器实例的函数指针。
 * 
 * @param store 要删除的数据读取器指针
 */
typedef void(*FuncDeleteDataReader)(IDataReader* store);

NS_WTP_END